package org.hawk.gwt.ppc.introspection.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.hawk.gwt.ppc.introspection.IntrospectionException;
import org.hawk.gwt.ppc.introspection.JavaConstructor;
import org.hawk.gwt.ppc.introspection.JavaField;
import org.hawk.gwt.ppc.introspection.JavaMethod;
import org.hawk.gwt.ppc.introspection.JavaTypeScope;
import org.hawk.gwt.ppc.introspection.JavaTypeVariable;

/**
 * Java type scope implementation for {@link Object} type.
 * 
 * @author alex.bereznevatiy@gmail.com
 *
 */
final class ObjectTypeScope extends AbstractJavaTypeScope {
	
	private List<JavaMethod> methods;

	ObjectTypeScope() {
		super(Object.class.getName(), null, new ArrayList<String>());
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#isInterface()
	 */
	public boolean isInterface() {
		return false;
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#isClass()
	 */
	public boolean isClass() {
		return true;
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#isEnum()
	 */
	public boolean isEnum() {
		return false;
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#isAnnotation()
	 */
	public boolean isAnnotation() {
		return false;
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#getConstructors()
	 */
	public List<JavaConstructor> getConstructors() {
		try {
			return Collections.singletonList((JavaConstructor)new JavaConstcructorImpl(Object.class.getConstructor(), this));
		} catch (Exception ex) {
			throw new IntrospectionException(ex);
		}
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#getMethods()
	 */
	public List<JavaMethod> getMethods() {
		if(methods==null){
			methods = new ArrayList<JavaMethod>();
			methods.add(getMethod("getClass"));
			methods.add(getMethod("equals", Object.class));
			methods.add(getMethod("toString"));
			methods.add(getMethod("hashCode"));
			methods = Collections.unmodifiableList(methods);
		}
		return methods;
	}

	private JavaMethod getMethod(String name, Class<?>...params) {
		try {
			return new JavaMethodImpl(Object.class.getDeclaredMethod(name, params), this);
		} catch (Exception ex) {
			throw new IntrospectionException(ex);
		}
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#getFields()
	 */
	public List<JavaField> getFields() {
		return Collections.singletonList(
				(JavaField)new JavaFieldImpl("class", "java.lang.Class", this));
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#getField(java.lang.String)
	 */
	public JavaField getField(String name) {
		if (name.equals("class")) {
			return new JavaFieldImpl("class", "java.lang.Class", this);
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#getDeclaredClasses()
	 */
	public List<JavaTypeScope> getDeclaredClasses() {
		return Collections.emptyList();
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#isPrimitive()
	 */
	public boolean isPrimitive() {
		return false;
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaTypeScope#isPrimitiveWrapper()
	 */
	public boolean isPrimitiveWrapper() {
		return false;
	}

	/* (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaParameterizable#getTypeVariables()
	 */
	public List<JavaTypeVariable> getTypeVariables() {
		return Collections.emptyList();
	}

	// will not be used
	@Override
	JavaField getDeclaredField(String name) {
		return null;
	}
}
